<template>

    <a-drawer
        :bodyStyle="{overflow: 'auto' }"
        :destroyOnClose="true"
        :title="title"
        :width="width"
        :visible="visible"
        :confirmLoading="confirmLoading"
        :maskClosable="true"
        :mask="true"
        :closable="true"
        @close="cancel"
      >
        
        <div class="table-page-search-wrapper">
      
            <a-row>
                <a-col :span="2">
                    <div class="flow-icon">
                        <div><i class="iconfont icon-24gl-circle"></i>开始</div>
                        <div><i class="iconfont icon-yuan"></i>结束</div>
                        <!-- <div @mousedown="createNode(flowSetting.flowCellType.网关节点,'sdp-gateway',$event)" ><i class="iconfont icon-lingxing"></i>网关</div> -->
                        <div @mousedown="createNode(flowSetting.flowCellType.任务节点,'sdp-task',$event)"><i class="iconfont icon-yuanjiaojuxing"></i>任务</div>
                        
                    </div> 
                </a-col>
                <a-col :span="14">
                    <a-row>
                       
                    </a-row>
                    <a-row>
                        <div id="sdp-flow-container"></div>
                    </a-row>
                    
                </a-col>
                <a-col :span="8" style="padding:10px;">
                    <div class="table-operator">
                        <a-button shape="round" size="small" type="primary" icon="plus" @click="ok">保存</a-button>
                        <LForm ref="LForm"  :formAttributes="formAttributes"></LForm>

                        <div style="margin-top:30px;">
                            <a-card v-if="currentClickCell" title="节点属性" :bordered="false" >
                                <nodeAttributeVue ref="nodeAttributeVue" :attribute="currentClickCellAttribute" @changeEventHandler="changeEventHandler"></nodeAttributeVue>
                            </a-card>
                        </div>
                        
                    </div>
                    
                </a-col>
            </a-row>
            
        </div>
   
        <div style="height:30px;"></div>
        <div class="drawer-bootom-button" v-if="isShowBootomButton">
            <a-button shape="round" @click="cancel" style="margin-right: .8rem">取消</a-button>
            <a-button  shape="round" @click="ok" type="primary" >提交</a-button>
        </div>
    </a-drawer>
</template>

<script>


import {SysMixin} from '@/mixins/SysMixin'
import defaultSettings from '@/config/defaultSettings'
import flowSetting from '@/components/lt/flow/flowSetting'
import { Graph } from '@antv/x6'
import { Dnd } from '@antv/x6-plugin-dnd'
import { Scroller } from '@antv/x6-plugin-scroller'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Selection } from '@antv/x6-plugin-selection'
import nodeAttributeVue from '@/components/lt/flow/nodeAttribute.vue'
import request from '@/utils/request'
import LForm from '@/components/lt/form/LForm'
import pick from 'lodash.pick'

//官方网址 https://x6.antv.antgroup.com/tutorial/basic/node
export default {
    name:'pageEdit',
    components:{nodeAttributeVue,LForm},
    mixins:[SysMixin],
    props:{
       
      
    },
    data(){
        return{
            visible:false,
            width:document.documentElement.clientWidth,
            confirmLoading:false,
            isShowBootomButton:false,
            model:{},
            title:'',
            defaultSettings,
            graph:null,
            dnd:null,
            activeKey:'1',
            flowSetting,
            //存的所有元素的属性数据
            cellAttributeData:{},
            //任务节点属性
            taskAttribute:{
                id:'',
                type:'',

            },
            currentClickCell:null,
            currentClickCellAttribute:null,
            formAttributes:{
              type:'',//collapse,tabs
              formItems:[
                {
                  title:'标签一',
                  columns:1,
                  fields:[
                    {field:'templateName',label:'模板名称',component:'input',rules: [{ required: true, message: '不能为空!' }]},
                    {field:'templateNo',label:'模版编号',component:'input',disabled:true,rules: [{required: false, message: '不能为空!'}]},
                    {field:'templateVersion',label:'模版版本',component:'input',disabled:true},
                    {field:'templateForm',label:'表单路径',component:'input',rules: [{required: false, message: '不能为空!'}]},
                    {field:'pageId',label:'自定义页面内码',component:'input',rules: [{required: false, message: '不能为空!'}]},
                  ]
                },
              ]

            }
        }
    },

    methods:{
        
        edit (record) {
            this.model = Object.assign({}, record);
            this.visible = true
            this.cellAttributeData={}
            this.currentClickCell=null
            this.currentClickCellAttribute=null
            this.$nextTick(() => {
                this.$refs.LForm.getForm().setFieldsValue(pick(this.model,'templateName','templateForm','templateNo','templateVersion','pageId'))
                this.initGraph()
                this.registerNode()
                if(record["keyId"]){
                    this.cellAttributeData=JSON.parse(require('js-base64').Base64.decode(this.model.templateAttribute))
                    this.graph.fromJSON(JSON.parse(require('js-base64').Base64.decode(this.model.templateGraph)))
                }else{
                    this.addStartNode()
                    this.addEndNode()
                }
            })
         
        },
       
        cancel(){
            this.visible=false
            this.$emit('handleCancel');
        },
        close () {
            this.active="1"
            this.visible = false
            this.$emit('close')
        },
        initGraph(){
            this.graph = new Graph({
                container: document.getElementById('sdp-flow-container'),
                autoResize: true,
                
                height: document.documentElement.clientHeight-100,
                background: {color: '#F2F7FA',},
                grid: {
                    visible: true,
                    type: 'doubleMesh',
                    args: [
                        {color: '#eee',thickness: 1, },
                        {color: '#ddd', thickness: 1, factor: 4,},
                    ],
                },
                connecting:{
                    snap: true, // 是否自动吸附
                    allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
                    allowNode: true, // 是否允许边链接到节点（非节点上的链接桩）
                    allowBlank: false, // 是否允许连接到空白点
                    allowLoop: false, // 是否允许创建循环连线，即边的起始节点和终止节点为同一节点，
                    allowEdge: true, // 是否允许边链接到另一个边
                    highlight: true, // 拖动边时，是否高亮显示所有可用的连接桩或节点
                    router: {
                        name: 'manhattan',
                        args: {
                            startDirections: ['top', 'right', 'bottom', 'left'],
                            endDirections: ['top', 'right', 'bottom', 'left'],
                        },
                    },
                    anchor: 'center',
                    connectionPoint: 'anchor',
                    validateConnection ({ targetMagnet }) {
                        return !!targetMagnet
                    },
                },
                highlighting: {
                    // 连接桩可以被连接时在连接桩外围围渲染一个包围框
                    magnetAvailable: {
                        name: 'stroke',
                        args: {
                            attrs: {
                                fill: '#fff',
                                stroke: '#A4DEB1',
                                strokeWidth: 4,
                            },
                        },
                    },
                    // 连接桩吸附连线时在连接桩外围围渲染一个包围框
                    magnetAdsorbed: {
                        name: 'stroke',
                        args: {
                            attrs: {
                                fill: '#fff',
                                stroke: '#31d0c6',
                                strokeWidth: 4,
                            },
                        },
                    },
                },
            })
            this.graph
                .use(new Scroller({enabled: true,}),)
                .use(new Snapline({enabled: true,}),)
                .use(new Selection({enabled: true,multiple: true,rubberband: true,movable: true,showNodeSelectionBox: true,}),)
            this.dnd=new Dnd({
                target: this.graph,
                scaled: false,
                getDropNode(node) {
                    let newNode = node.clone({ keepId: true })
                    newNode["type"]=node.type
                    return newNode
                },
                getDragNode: (node) => {
                    let newNode = node.clone({ keepId: true })
                    newNode["type"]=node.type
                    return newNode
                }
            })
            // this.graph.on('node:port:mouseup', ({ e, x, y, node, view}) => {
            //     console.log(x,y,node)
            // })

            //我们可以通过 isNew 来判断连线完成后，对应的边是否是新创建的边。比如从一个连接桩开始，创建了一条边并连接到另一个节点/连接桩，此时 isNew 就为 true
            this.graph.on('edge:connected', ({ isNew, edge }) => {
                let that = this
                if (isNew) {
                    //给边添加工具
                    edge.addTools([{name: 'button-remove',args:{distance:-20,onClick({ e,cell,view }) { that.remove(e,cell,view) }}},{name:'segments'},{name:'vertices'}])
                    edge['type']=that.flowSetting.flowCellType.边.type
                    edge.appendLabel({
                        attrs: {
                            text: {
                                text: that.flowSetting.flowCellType.边.label,
                            },
                        },
                        position: {offset: -10,},
                    })
                    
                    //修改边的颜色
                    // edge.attr('line/stroke', '#ccc')
                    that.setCellAttributeData(edge)
                }
            })

            //节点右键点击事件
            this.graph.on('node:contextmenu',({ e, x, y, cell, view }) => {
                this.activeKey="2"
                this.currentClickCell = cell
                this.currentClickCellAttribute = this.cellAttributeData[cell.id]
                // console.log(cell)
            })

            //边右键事件
            this.graph.on('edge:contextmenu', ({ e, x, y, edge, view }) => {
                //如果是从开始节点出来的，不做处理
                
                this.activeKey="2"
                this.currentClickCell = edge
                this.currentClickCellAttribute = this.cellAttributeData[edge.id]
                // console.log(edge)
            })
        },
        //重新定制节点样式
        registerNode(){
            //任务节点
            Graph.registerNode('sdp-task',{
                inherit: 'rect', // 继承于 rect 节点
                width: 100,
                height: 60,
                markup:[
                    {tagName: 'rect',selector: 'body',},
                    {tagName: 'image',selector: 'img',},
                    {tagName: 'text',selector: 'label',},
                ],
                attrs:{
                    body: {
                        stroke: '#8f8f8f',strokeWidth: 1,fill: '#fff',rx: 6,ry: 6,
                    },
                    img:{}
                },
                ports:{
                    groups:{
                        top: {
                            position: 'top',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        bottom: {
                            position: 'bottom',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        left: {
                            position: 'left',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        right: {
                            position: 'right',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                    }
                }
            },true)

            //重新定制圆形节点
            Graph.registerNode('sdp-circle',{
                inherit: 'circle', // 继承于 circle 节点
                width: 60,
                height: 60,
                markup:[
                    {tagName: 'circle',selector: 'body',},
                    {tagName: 'image',selector: 'img',},
                    {tagName: 'text',selector: 'label',},
                ],
                attrs:{
                    label:{
                        refX: 0.5,
                        refY: -10,
                    },
                    body: {
                        stroke: '#8f8f8f',strokeWidth: 1,fill: '#fff',rx: 6,ry: 6,
                    },
                    img:{}
                },
                ports:{
                    groups:{
                        top: {
                            position: 'top',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        bottom: {
                            position: 'bottom',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        left: {
                            position: 'left',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        right: {
                            position: 'right',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        center:{
                            position:'absolute',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 10,},},
                        },
                        ellipseSpread:{
                            
                            position:'ellipseSpread',
                            attrs: {start: 45,circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        }

                    }
                }
            },true)

            //菱形
            Graph.registerNode('sdp-gateway',{
                inherit: 'polygon', // 继承于 rect 节点
                width: 60,
                height: 60,
                markup:[
                    {tagName: 'polygon',selector: 'body',},
                    {tagName: 'image',selector: 'img',},
                    {tagName: 'text',selector: 'label',},
                ],
                attrs:{
                    body: {
                        stroke: '#8f8f8f',strokeWidth: 1,fill: '#fff',refPoints: '0,10 10,0 20,10 10,20',
                    },
                    img:{}
                },
                ports:{
                    groups:{
                        top: {
                            position: 'top',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        bottom: {
                            position: 'bottom',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        left: {
                            position: 'left',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                        right: {
                            position: 'right',
                            attrs: {circle: {magnet: true,stroke: '#8f8f8f',r: 5,},},
                        },
                    }
                }
            },true)
        },
        //添加开始节点
        addStartNode(){
            let flowStartNode = this.graph.addNode({
                shape: 'sdp-circle',
                label:this.flowSetting.flowCellType.开始节点.label,
                x: 200,
                y: 140,
                // tools: ['button-remove'],
                ports: {
                    items: [
                        {
                            group: 'center',
                            args: {
                                x: '50%',
                                y: '50%',
                                
                            },
                        },
                       
                    ],
                },
            })
            flowStartNode['type']=this.flowSetting.flowCellType.开始节点.type
            this.setCellAttributeData(flowStartNode)
        },

         //添加结束节点
        addEndNode(){
            let flowEndNode = this.graph.addNode({
                shape: 'sdp-circle',
                label:this.flowSetting.flowCellType.结束节点.label,
                x: 500,
                y: 140,
                // tools: ['button-remove'],
                attrs:{
                    body: {stroke: '#000000',strokeWidth: 3,},
                },
                ports: {
                    items: [
                        {
                            group: 'center',
                            args: {
                                x: '50%',
                                y: '50%',
                                
                            },
                        },
                       
                    ],
                },
                
            })
            flowEndNode["type"]=this.flowSetting.flowCellType.结束节点.type
            this.setCellAttributeData(flowEndNode)

            // Array.from({ length: 10 }).forEach((_, index) => {
            //     flowEndNode.addPort({
            //         id: `${index}`,
            //         group: 'ellipseSpread',
       
            //     })
            // })
        },
        createNode(cellType,shape, e){
            let that = this
            let node = this.graph.createNode({
                shape: shape,
                label:cellType.label,
                tools: [{name:'button-remove',args:{onClick({ e,cell,view }) { that.remove(e,cell,view) },}}],
                ports: {
                    items: [
                        {group: 'top',},
                        {group: 'bottom',},
                        {group: 'left',},
                        {group: 'right',},
                    ],
                },
            })
            node["type"]=cellType.type
            this.dnd.start(node, e)
            this.setCellAttributeData(node)
            
        },
        //保存
        ok(){
            if(!this.graph || !this.cellAttributeData ){
                this.$message.warning("数据不存在")
                return false
            }
            let cellArr = this.graph.toJSON().cells
            if(cellArr.length<5){
                this.$message.warning("流程不完整")
                return false
            }
            // console.log(this.graph.toJSON())
            // console.log(this.cellAttributeData)

            let that = this
            that.confirmLoading=true

            //生成节点跳转数据
            let flowJumpData={}
            for(let c of this.graph.toJSON().cells){
                if(c.shape=="edge"){
                    if(flowJumpData[c.source.cell]){
                        flowJumpData[c.source.cell].endNodeArr.push({"endNodeId":c.target.cell,"condition":this.cellAttributeData[c.id]["condition"],"endNodeLabel":this.cellAttributeData[c.target.cell]["label"],"isReturn":this.cellAttributeData[c.id]["isReturn"]})
                    }else{
                        let endNodeArr = []
                        endNodeArr.push({"endNodeId":c.target.cell,"condition":this.cellAttributeData[c.id]["condition"],"endNodeLabel":this.cellAttributeData[c.target.cell]["label"],"isReturn":this.cellAttributeData[c.id]["isReturn"]})
                        flowJumpData[c.source.cell] = {"startNodeId":c.source.cell,"startNodeLabel":this.cellAttributeData[c.source.cell]["label"],"endNodeArr":endNodeArr}
                    }
                }
                
            }

            // console.log(flowJumpData)
            // console.log(this.cellAttributeData)

            //数据检测
            //开始节点只能到一个节点

            //结束节点不能再链接到其他节点

            //如果一个节点可以去多个节点，则只能有一个边的表达式为空，其他必须有条件
            let firstTask = null
            for (const key in this.cellAttributeData) {
                let c = this.cellAttributeData[key]
                if(c.type==this.flowSetting.flowCellType.开始节点.type){
                    if(flowJumpData[c.id].endNodeArr.length>1){
                        this.$message.warning("开始节点不能同时指向多个节点")
                        return false
                    }
                    //获取流程的第一个节点
                    firstTask = flowJumpData[c.id].endNodeArr[0].endNodeId

                }else if(c.type==this.flowSetting.flowCellType.结束节点.type){
                    if(flowJumpData[c.id]){
                        this.$message.warning("结束节点不能再指向其他节点")
                        return false
                    }
                }else if(c.type==this.flowSetting.flowCellType.任务节点.type){
                    if(!c.label){
                        this.$message.warning("节点:"+c.id+"名称为空")
                        return false
                    }
                    //判断节点的属性是否有必填的没有填写
                    if(c.assigneeMode==this.flowSetting.constant.指定人员){
                        if(!c.assigneeEmpName){
                            this.$message.warning("节点:"+c.id+"指定的人员为空")
                            return false
                        }
                    }else if(c.assigneeMode==this.flowSetting.constant.指定角色){
                            if(!c.assigneeRole){
                            this.$message.warning("节点:"+c.id+"指定的角色为空")
                            return false
                        }   
                    }
                    if(flowJumpData[c.id] && flowJumpData[c.id].endNodeArr.length>1){
                        //先判断是否有重复的路径
                        const uniqueEndNodeArr = new Set(flowJumpData[c.id].endNodeArr.map(item => item.endNodeId));
                        if(flowJumpData[c.id].endNodeArr.length !== uniqueEndNodeArr.size){
                            this.$message.warning("节点:"+c.id+"有重复路径")
                            return false
                        }

                        //判断是否有多个跳转条件为空
                        let emptyEdgeCount = 0
                        for(let node of flowJumpData[c.id].endNodeArr){
                            if(!node.condition){
                                emptyEdgeCount++
                            }
                        }
                        if(emptyEdgeCount>1){
                            this.$message.warning("节点:"+c.id+"有多个边的跳转条件为空")
                            return false
                        }

                       
                        
                    }
                }
               
            }
            
            this.$refs.LForm.getForm().validateFields((err, values) => {
                if (!err) {
                    that.confirmLoading = true
                    let formData = Object.assign(this.model, values)
                    formData["templateGraph"]=require('js-base64').Base64.encode(JSON.stringify(that.graph.toJSON()))
                    formData["templateAttribute"]=require('js-base64').Base64.encode(JSON.stringify(that.cellAttributeData))
                    formData["templateJumpData"]=require('js-base64').Base64.encode(JSON.stringify(flowJumpData))
                    formData["startNode"]=firstTask
                    request({url: '/SysFlowTemplateController/save',method: 'post',data:formData}).then((res)=>{
                        if(res.success){
                            that.close()
                            that.$message.success(res.message);
                        }else{
                            that.$message.warning(res.message);
                        }
                    }).finally(() => {
                        that.confirmLoading = false;
                        
                    })
                    
                }
            })
        },
        //删除元素
        remove(e,cell,view){
            cell.remove()
            if(this.cellAttributeData[cell.id]){
                delete this.cellAttributeData[cell.id]
            }
        },
        setCellAttributeData(cell){
            if(!this.cellAttributeData[cell.id]){
                this.cellAttributeData[cell.id]={
                    id:cell.id,
                    type:cell.type
                }
            }
           
            if(this.flowSetting.flowCellType.任务节点.type==cell.type || this.flowSetting.flowCellType.开始节点.type==cell.type || this.flowSetting.flowCellType.结束节点.type==cell.type){
                this.cellAttributeData[cell.id]['label']=cell.attrs.text.text
            }else if(this.flowSetting.flowCellType.边.type==cell.type){
                this.cellAttributeData[cell.id]['label']=cell.labels[0].attrs.text.text
            }
        },
        
        changeEventHandler(item){
            // console.log(item)
            // console.log(this.currentClickCell)
            let nodeAttr = this.cellAttributeData[this.currentClickCell.id]
            if(item["label"]){
                if(this.flowSetting.flowCellType.任务节点.type==nodeAttr.type || this.flowSetting.flowCellType.开始节点.type==nodeAttr.type || this.flowSetting.flowCellType.结束节点.type==nodeAttr.type){
                    this.currentClickCell.attr('label', {text: item.label})
                }else if(this.flowSetting.flowCellType.边.type==this.currentClickCell.type){
                    this.currentClickCell.setLabels(item.label)
                }
                
            }
        }
       
    }

}
</script>
<style scoped src="../../../assets/iconfont/iconfont.css">
   
</style>

<style scoped>
 .flow-icon div{ line-height:42px;}
 .flow-icon .iconfont{ margin-right:6px; font-style: normal; font-size:24px;float: left;}
</style>
